using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace SteeringBehaviors
{
    abstract public class Rendering
    {
        #region PRIVATE MEMBERS

        static private float globalScale = 1f;
        static private Vector3 worldSize = new Vector3(1600f, 1200f, 0f);
        static private Vector3 worldOffset = new Vector3();
        static private SortedList<string, Texture> textureMap = new SortedList<string, Texture>();
        
        #endregion

        #region PROPERTIES

        /// <summary>
        /// The size of the rendering area
        /// </summary>
        static public Vector3 WorldSize
        {
            get { return worldSize; }
            set { worldSize = value; }
        }

        /// <summary>
        /// The scale of objects being rendered
        /// </summary>
        static public float GlobalScale
        {
            get { return globalScale; }
            set { globalScale = value; WorldOffset = WorldOffset; }
        }

        /// <summary>
        /// The amount to offset objects being rendered
        /// </summary>
        static public Vector3 WorldOffset
        {
            get { return worldOffset; }
            set
            {
                if (value.X < 0)
                    value.X = 0;
                if (value.Y < 0)
                    value.Y = 0;
                Vector3 viewSize = new Vector3();
                viewSize = WorldSize * (1/GlobalScale);
                if (viewSize.X + value.X > WorldSize.X)
                    value.X = WorldSize.X - viewSize.X;
                if (viewSize.Y + value.Y > WorldSize.Y)
                    value.Y = WorldSize.Y - viewSize.Y;
                worldOffset = value;
            }
        }

        #endregion

        #region INTERFACE METHODS

        /// <summary>
        /// Renders a baseobject (or dirived class) to the screen
        /// </summary>
        /// <param name="bobject">object to render</param>
        /// <param name="sprite">directx sprite object to use for rendering</param>
        static public void Render(BaseObject bobject, Sprite sprite)
        {
            if (!textureMap.ContainsKey(bobject.Image))
                textureMap[bobject.Image] = TextureLoader.FromFile(sprite.Device, bobject.Image);

            // set up matricies to determine where to render
            Matrix transform = new Matrix();
            transform = Matrix.Identity;

            // compute scaling in x and y axis
            float x = Convert.ToSingle(bobject.Dimensions.Width) / Convert.ToSingle(bobject.ImageDimensions.Width) * GlobalScale,
                y = Convert.ToSingle(bobject.Dimensions.Height) / Convert.ToSingle(bobject.ImageDimensions.Height) * GlobalScale;

            // setup scaling matrix and
            // apply scaling to transform
            transform.Multiply(Matrix.Scaling(new Vector3(x, y, 1)));

            // setup rotation matrix and
            // apply rotation to transform
            transform.Multiply(Matrix.RotationZ(Convert.ToSingle(bobject.Heading)));

            // setup translate matrix and
            // apply translation to transform
            transform.Multiply(Matrix.Translation((bobject.Position - WorldOffset) * GlobalScale));

            // apply transform to sprite object
            sprite.Transform = transform;

            sprite.Draw(textureMap[bobject.Image], new Vector3(Convert.ToSingle(bobject.ImageDimensions.Width >> 1), Convert.ToSingle(bobject.ImageDimensions.Height >> 1), 0),
                new Vector3(), bobject.DXColor.ToArgb());
        }

        /// <summary>
        /// Clears all textures from memory.
        /// </summary>
        static public void ClearAllTextures()
        {
            textureMap.Clear();
        }

        #endregion
    }
}
